//-------------------------------------------------------------------------------
//!\file	Timer.cpp
// \author	Pete Kugler and John Jensen
// \date	Wednesday, October 9, 2004
// \par		license
//			All content (c) 2005, DigiPen (USA) Corporation, all rights reserved.
// \brief	This is the implementation file for the CTimer class which creates 
//			a timer to be used by the game application. The class will first try 
//			to initialize itself with the performance timer, however if that 
//			fails, then the default multimedia timer is used. 
//		  
//				Operations include:
//					- initializing the timer with the performance/multimedia 
//					  timer
//					- reset the timer
//-------------------------------------------------------------------------------



#include "Timer.h"

#pragma warning(push)
#pragma warning(disable: 4201) // disable warnings from Mmsystem.h
#include <windows.h>
#include <Mmsystem.h> // for timeGetTime
#pragma warning(pop)

/*!===============================================================================
\brief	Default constructor, set all members to zero
\param	bDefMM
		Default to timeGetTime()?
*///==============================================================================
CTimer::CTimer(bool bDefMM/* = false */)
: pfnUpdate_(NULL)
{	
	dBaseTime_    = 0.0;
	dLastTime_    = 0.0;
	fSecsPerTick_ = 0.0;
	
	dCurrentTime_ = 0.0;
	fFrameTime_   = 0.0f;
	
	nTimerStart_.QuadPart  = 0;
	nCurrentTime_.QuadPart = 0;

	Init(bDefMM);
}

/*!===============================================================================
\brief	Destructor, clears the function pointer
*///==============================================================================
CTimer::~CTimer()
{
}

/*!===============================================================================
\brief	Function initializes the timer
\param	bDefMM
		Default to timeGetTime()?
*///==============================================================================
void CTimer::Init(bool bDefMM)
{
	LARGE_INTEGER nTicksPerSec;

	// first check for performance counter
	if (QueryPerformanceFrequency(&nTicksPerSec) && !bDefMM)
	{ 
		QueryPerformanceCounter(&nTimerStart_);
		fSecsPerTick_ = 1.0 / nTicksPerSec.QuadPart;
		pfnUpdate_    = &CTimer::GetPerformanceCounterTime;
	}
	else	// use multimedia timer
	{ 
		nTimerStart_.QuadPart  = timeGetTime();
		fSecsPerTick_ = 1.0 / 1000.0;
		pfnUpdate_    = &CTimer::GetMMTime;
	}
}

/*!===============================================================================
\brief	Function updates the time in the application
\return void
		returns nothing 
*///==============================================================================
void CTimer::Update()
{
	dCurrentTime_ = (this->*pfnUpdate_)() - dBaseTime_;
	fFrameTime_   = float(dCurrentTime_ - dLastTime_);
	dLastTime_    = dCurrentTime_;
}

/*!===============================================================================
\brief	Function resets the timer
*///==============================================================================
void CTimer::Reset()
{
	dBaseTime_ =  (this->*pfnUpdate_)();
	dLastTime_ = dCurrentTime_ = 0.0;
	fFrameTime_ = 0.0f;
}


/*!===============================================================================
\brief	Function resets the timer to /p fTime
\param	fTime
		Time, in seconds, to set the timer to.
*///==============================================================================
void CTimer::SetTime(double fTime)
{
	dBaseTime_ = (this->*pfnUpdate_)();
	dLastTime_ = 0.0;
	dCurrentTime_ = fTime;
}

/*!===============================================================================
\brief	Function updates the times with the performance counter 
\return double
		returns the elasped time
*///==============================================================================
double CTimer::GetPerformanceCounterTime()
{
	QueryPerformanceCounter(&nCurrentTime_);
	return (fSecsPerTick_ * (nCurrentTime_.QuadPart - nTimerStart_.QuadPart));
}

/*!===============================================================================
\brief	Function updates the times with the crappy multimedia counter 
\return double
		returns the elasped time
*///==============================================================================
double CTimer::GetMMTime()
{	
	return (fSecsPerTick_ * (timeGetTime()- nTimerStart_.QuadPart));
}

